# coding=utf-8
import face_recognition
import cv2
import numpy as np
import requests
from io import BytesIO
from PIL import Image
from com.py.test.face_recogn.FaceRecognWeb import ft2
from com.py.test.face_recogn.Thread.MyThread import MyThread
import time

class FaceRecognByNet:
    def __init__(self):
        self.http = "http://localhost:9099/"
        self.known_face_encodings = []
        self.known_face_names = []

        self.connectRemoteHouse()
        self.crowVideoRead()  #捕获视频，识别
    def crowVideoRead(self): #捕获视频，识别
        #获取对网络摄像机的引用0（默认值）
        video_capture = cv2.VideoCapture(0)
        # Initialize some variables
        face_locations = []
        face_encodings = []
        face_names = []
        process_this_frame = True

        while True:
            # 抓取一帧视频
            ret, frame = video_capture.read()
            # 将视频帧的大小调整为1/4，以便更快地进行人脸识别处理
            # small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)  #近距离检测
            small_frame = cv2.resize(frame, (0, 0), fx=1, fy=1)
            # 将图像从bgr颜色（opencv使用）转换为rgb颜色（人脸识别使用）
            rgb_small_frame = small_frame[:, :, ::-1]
            # 只处理其他每帧视频以节省时间
            if process_this_frame:
                # 查找当前视频帧中的所有面和面编码
                face_locations = face_recognition.face_locations(rgb_small_frame)
                face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

                face_names = []
                for face_encoding in face_encodings:

                    # 查看人脸是否与已知人脸匹配
                    matches = face_recognition.compare_faces(self.known_face_encodings, face_encoding)
                    name = "未知人员"

                    # # 如果在已知的面部编码中发现匹配，只需使用第一个。
                    # if True in matches:
                    #     first_match_index = matches.index(True)
                    #     name = known_face_names[first_match_index]

                    # 或者，使用与新面距离最小的已知面
                    face_distances = face_recognition.face_distance(self.known_face_encodings, face_encoding)
                    best_match_index = np.argmin(face_distances)
                    if matches[best_match_index]:
                        name = self.known_face_names[best_match_index]
                    face_names.append(name)

            process_this_frame = not process_this_frame

            # Display the results
            for (top, right, bottom, left), name in zip(face_locations, face_names):
                # 自我们检测到的帧被缩放到1/4大小后，将备份面位置缩放
                #近距离检测
                # top *= 4
                # right *= 4
                # bottom *= 4
                # left *= 4
                #远距离检测
                top *= 1
                right *= 1
                bottom *= 1
                left *= 1

                # 在脸上画一个方框
                # cv2.rectangle(frame, (round(left), round(top)), (round(right), round(bottom)), (0, 0, 255),cv2.FILLED)
                cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
                # 在面下绘制一个名称为的标签
                # cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
                # font = cv2.FONT_HERSHEY_DUPLEX
                #设置中文名称
                ft = ft2.put_chinese_text('font/msyh.ttc')
                text_size = 24
                frame = ft.draw_text(frame, (left, bottom - 6), name, text_size,(0,0, 255))
                # frame =  ft.draw_text(frame,(left, bottom - 6), "王俊凯", font,(0,255, 0))
             # cv2.putText(frame, name, (left, bottom - 6), font, 1.0, (0,0, 0), 1)
            # Display the resulting image
            cv2.imshow('Video', frame)

            # 点击键盘上的“Q”退出！
            if cv2.waitKey(1) & 0xFF == ord('q'):
                exit(0)

        # Release handle to the webcam
        video_capture.release()
        cv2.destroyAllWindows()
    def connectRemoteHouse(self):  #；连接脸部仓库
        print("~~~请求远程仓库~~~~")
        #请求仓库文件
        filesRq = requests.get(self.http+"index/files.txt")
        filesRq.encoding = 'utf-8' #设置编码
        filenames = filesRq.text.split("\t")
        size = len(filenames)
        step = 20 #20人 6.06分钟，6.18 10人 6.18为一组 100 6.75  50 6.73
        groups = [filenames[i:i+step] for i in range(0,size,step)]
        thread_num = len(groups)  #线程数
        startTime = time.time()
        print("开启线程数为：",thread_num)
        li = []
        for i in range(thread_num):
            t = MyThread(self.run_thread,args=(self,groups[i],i))
            li.append(t)
            t.start()
        for t in li:
            t.join()  # 一定要join，不然主线程比子线程跑的快，会拿不到结果
            # print(t.get_result())
        endTime = time.time()
        print("所有线程结束！")
        print("人脸数有:%s,载入人脸花费时间为:%d" % (size,endTime-startTime))
        # print(filenames)
        #init param

        # for filename in filenames:

        print("~请求远程仓库结束~")
    def load_web_photo(self,url, mode='RGB'):
        rq = requests.get(url)
        im = Image.open(BytesIO(rq.content))
        if mode:
            im = im.convert(mode)
        return np.array(im)
    def run_thread(self,target,filenames,num):
        # print("线程开启：",num,end='')
        for filename in filenames:
            print(time.time(),num)
            try:
                target.known_face_encodings \
                    .append(face_recognition.face_encodings(target.load_web_photo(target.http+filename))[0])
                spath = filename.split(".")[0]
                if spath.find("/")==-1:
                    target.known_face_names.append(spath)
                else:
                    target.known_face_names.append(spath.split("/")[1])
                # raw_landmarks = _raw_face_landmarks(face_image, known_face_locations, model="small")
                # [np.array(face_encoder.compute_face_descriptor(face_image, raw_landmark_set, num_jitters)) for raw_landmark_set in raw_landmarks]
            except OSError as e:
                print("图片不存在！",filename)
                continue
            except IndexError:
                print("图片不能识别！",filename)
                # print(face_recognition.face_encodings(self.load_web_photo(self.http+filename)))
                # raw_landmarks = face_landmarks(self.load_web_photo(self.http+filename), None, model="small")
                # print(raw_landmarks)
                continue
                # exit(0) #终止程序
        return num
FaceRecognByNet()